<?xml version="1.0"?>
<OnTheFlyInstruction xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <InstanceId>Web Iterator</InstanceId>
  <CustomAppConfig />
  <Tags>
    <string>SharePoint Client</string>
  </Tags>
  <AdditionalAssemblies />
  <Code><![CDATA[// ----------------------
//  Web iterator
//	Lists all sites in the 'Data Table' tab with AllProperties (property bag)
//	User 'Process' method to execute code per site
// ----------------------
// v 0.0.1 mm - added a subquery type filter

using System; using System.Data;
using System.Linq;using System.Net;
using Microsoft.SharePoint.Client;
using xSolon.Instructions;
using xSolon.Instructions.DTO;
using System.Collections.Generic;
using xSolon.SP.ManagedClient;

public class SP14Client_Sample : AbstractInstruction
{
	NetworkCredential creds = null;
	List<Dictionary<string, string>> sites = new List<Dictionary<string, string>>();
	
    public override void Run()
    {
    	string domain = "http://localhost/";

        SP14ClientHelper instr = new SP14ClientHelper();

        creds = this.CredentialCache.First();

		string url = domain + ""; // target a sub web
	
        var ctx = instr.GetContext(url,SP14AuthenticationType.Windows, creds);

		ProcessWeb(ctx, ctx.Web);
		
		ResultTable = ToWebInstr.PrepareTable(sites.ListToTable());

    }

	void Add(Web web)
    {
        var row = new Dictionary<string, string>();

        NotifyInformation(web.ServerRelativeUrl);

        row.Add("Url", web.ServerRelativeUrl);
        row.Add("Title", web.Title);
        
        foreach(var kv in web.AllProperties.FieldValues)
		{
			//NotifyInformation("{0}:{1}",kv.Key,kv.Value);
			var value1 = "";
			
			if(kv.Value != null) value1 = kv.Value.ToString();
			
			row.Add(kv.Key,value1);
		}
		
        /*
        	row.Add("WebTemplateId", web.web .WebTemplateId.ToString());
        	row.Add("WebTemplate", web.WebTemplate);
        	row.Add("Configuration", web.Configuration.ToString());
		*/
        sites.Add(row);
    }

	void ProcessWeb(ClientContext ctx, Web web)
	{
		if (this.StopPending) return;
		
		ctx.Load(web);
		
		WebCollection subWebs = null;
		
		// Get Sub webs with a tempalte type filter
		/*var query = new SubwebQuery();
		query.WebTemplateFilter = 91862;
		query.ConfigurationFilter = 2;
		WebCollection subWebs = web.GetSubwebsForCurrentUser(query);
		*/
		// or get All
		subWebs = web.Webs;
		
		ctx.Load(subWebs);
		ctx.Load(web.AllProperties);
		ctx.ExecuteQuery();
		
		NotifyInformation("Processing {0}...",web.ServerRelativeUrl);
	
		foreach(Web i in subWebs.ToList())
		{
			if (this.StopPending) break;
			ProcessWeb(ctx,i);
		};
		
		Add(web);
	}
	
	DataTable GetTableFromItems(ListItemCollection items)
	{
		var list1 = new List<Dictionary<string,string>>();
				
				items.ToList().ForEach(i =>
				{
					var temp = new Dictionary<string,string>();
					
					i.FieldValues.ToList().ForEach( x => temp.Add(x.Key, (x.Value == null) ? "" : x.Value.ToString()));
					
					list1.Add(temp);
				});
				
				
				return list1.ListToTable();
	}
}

public class WebInstruction
{
	public List<WebInstruction> Webs = new List<WebInstruction>();
	public string DisplayName;
	public string SiteDefinition;
	public string Name;
}

// Internal helper to turn a table of sites into a XMl site hierarchy
class ToWebInstr
{
    static List<Dictionary<string, string>> GetDirectSubs(Dictionary<string, string> curent, List<Dictionary<string, string>> sites)
    {
        var filter = string.Format("{0}/", curent["Url"]);

        var subs = sites.Where(i => i["Url"].StartsWith(filter)).ToList();

        subs.ForEach(i => i["Url"] = i["Url"].Substring(filter.Length));

        var directSubSites = subs.Where(i => i["Url"].IndexOf("/") < 0).ToList();

        return directSubSites;
    }

    internal static WebInstruction WebFull(Dictionary<string, string> curent, List<Dictionary<string, string>> sites)
    {
        var web = WebInstructionDic(curent);

        sites.Remove(curent);

        var subs = GetDirectSubs(curent, sites);

        subs.ForEach(i =>
        {
            web.Webs.Add(WebFull(i, sites));
        });

        return web;
    }

    static WebInstruction WebInstructionDic(Dictionary<string, string> dic)
    {
        var web = new WebInstruction();

        web.DisplayName = dic["Title"];

        web.Name = dic["Url"];
        web.SiteDefinition = string.Format("{0}#1", dic["WebTemplate"]);

        return web;
    }

    public static int Count(String ii, String substring)
    {
        int count = 0;
        int idx = 0;

        while ((idx = ii.IndexOf(substring, idx)) != -1)
        {
            idx++;
            count++;
        }

        return count;
    }

    internal static DataTable PrepareTable(DataTable dt)
    {
        var sorted = Sort("ASC", dt, dt.Columns["Url"]);

        sorted = RemoveDuplicates(sorted, "Url");

        return sorted;
    }

    static DataTable RemoveDuplicates(DataTable table, string columnName)
    {
        var urls = new List<string>();

        var rowsToRemove = new List<DataRow>();

        foreach (DataRow row in table.Rows)
        {
            var url = row[columnName].ToString();

            if (urls.Contains(url))
            {
                rowsToRemove.Add(row);
            }
            else
            {
                urls.Add(url);
            }
        }

        rowsToRemove.ForEach(i => table.Rows.Remove(i));

        table.AcceptChanges();

        return table;
    }

    static DataTable Sort(string dir, DataTable table, DataColumn sortRow)
    {
        var newTable = table.Clone();
        EnumerableRowCollection<DataRow> query = null;

        #region Get Query

        if (sortRow.DataType == typeof(String))
        {
            query = from order in table.AsEnumerable()
                    orderby order.Field<String>(sortRow.ColumnName)
                    select order;
        }
        else if (sortRow.DataType == typeof(int))
        {
            query = from order in table.AsEnumerable()
                    orderby order.Field<int>(sortRow.ColumnName)
                    select order;
        }
        else if (sortRow.DataType == typeof(DateTime))
        {
            query = from order in table.AsEnumerable()
                    orderby order.Field<DateTime>(sortRow.ColumnName)
                    select order;
        }

        #endregion

        query.ToList().ForEach(i =>
        {
            newTable.ImportRow(i);
        });

        newTable.AcceptChanges();

        return newTable;
    }
}]]></Code>
</OnTheFlyInstruction>